#include "widget.h"
#include "ui_widget.h"
#include "thread.h"
#include <QFile>
#include <QFileDialog>
#include <QThread>
#include <QDebug>
#include <QFileInfo>
#include <QDateTime>
#include <QDir>
#include <QMessageBox>
#include <QByteArray>
#include <QCryptographicHash>
#include <QDateTime>
#include <QProgressDialog>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置窗口固定大小
    setFixedSize(650,550);
    //close window
    connect(ui->pushButton, &QPushButton::clicked, this, &Widget::close);
    //create thread
    //读取文件夹路径
    connect(ui->pushButton1, &QPushButton::clicked, [=](){
       path1 = QFileDialog::getExistingDirectory(this, "open file/directory", "/home");
       ui->lineEdit_2->setText(path1);
    });
    connect(ui->pushButton2, &QPushButton::clicked, [=](){
       path2 = QFileDialog::getExistingDirectory(this, "open file/directory", "/home");
       ui->lineEdit->setText(path2);
    });
    connect(ui->findFile, &QPushButton::clicked, this, &Widget::SlotFindFileAndDir);
    connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::SlotFindFileAndDir2);
    connect(ui->pushButton_3, &QPushButton::clicked, this, &Widget::SlotCopyDir);
    connect(ui->pushButton_7, &QPushButton::clicked, this, &Widget::clearText);
    connect(ui->pushButton_4, &QPushButton::clicked, this, &Widget::AtoB);
    connect(ui->pushButton_5, &QPushButton::clicked, this, &Widget::BtoA);
    connect(ui->pushButton_6, &QPushButton::clicked, this, &Widget::ComAB);

}


bool Widget::findFile(QString path, int flag)
{
    QDir dir(path);
    if (!dir.exists()) {
        return false;
    }
    dir.setFilter(QDir::Files|QDir::Dirs);
    dir.setSorting(QDir::Name);
    QFileInfoList list = dir.entryInfoList();
    /*
    for (int j = 0; j != list.size(); j++) {
        qDebug() << list.at(j).absoluteFilePath();
    }
    qDebug() << "end***";
    */
       int i = 0;

       bool bIsDir;
       do
       {
           QFileInfo fileInfo = list.at(i);
           if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
           {
               ++i;
               continue;
           }
           bIsDir = fileInfo.isDir();
           if(bIsDir)
           {
               //qDebug() << "absoluteFilePath=" << fileInfo.absoluteFilePath();
               sum++;
               QString str = "Path=";
               str.append(fileInfo.absoluteFilePath());
               if (flag == 1) ui->textEdit->append(str);
               else if (flag == 2) ui->textEdit_2->append(str);
               findFile(fileInfo.filePath(), flag);
           }
           else
           {
               //qDebug() << "absoluteFilePath=" << fileInfo.absoluteFilePath();
               sum++;
               QString str = "Path=";
               str.append(fileInfo.absoluteFilePath());
               if (flag == 1) ui->textEdit->append(str);
               else if (flag == 2) ui->textEdit_2->append(str);
           }
           ++i;
       }while(i < list.size());

       return true;
}
void Widget::SlotFindFileAndDir()
{
    sum = 0;
    QString strDir = path1;
    qDebug() << path1;
    findFile(strDir, 1);
    qDebug() << "遍历: " << path1;
}
void Widget::SlotFindFileAndDir2()
{
    QString strDir = path2;
    qDebug() << path2;
    findFile(strDir, 2);
    qDebug() << "遍历: " << path2;
}

void Widget::SlotCopyDir()
{
    //设置进度条对话框
    QProgressDialog dialog(tr("任务进度"), tr("取消"), 0, sum, this);
    dialog.setWindowTitle(tr("进度对话框"));
    dialog.setWindowModality(Qt::WindowModal);
    dialog.show();
    for(int i = 0; i < sum; i++)
    {
        dialog.setValue(i);
        QCoreApplication::processEvents();
        if(dialog.wasCanceled())
            break;
         QThread::msleep(10);
    }
    QString fromDir = path1;
    QString toDir = path2;
    copyDir(fromDir, toDir, false);
    dialog.setValue(sum);
    qDebug() << "将" << fromDir << "备份到" << toDir;
    QMessageBox::information(NULL, "文件备份", "文件备份完成^_^", QMessageBox::Yes);
}

//拷贝文件夹：
bool Widget::copyDir(const QString fromDir, const QString toDir, bool coverFileIfExist)
{
    QDir sourceDir(fromDir);
    QDir targetDir(toDir);
    if(!targetDir.exists()){    /* 如果目标目录不存在，则进行创建 */
        if(!targetDir.mkdir(targetDir.absolutePath()))
            return false;
    }

    QFileInfoList fileInfoList = sourceDir.entryInfoList();
    foreach(QFileInfo fileInfo, fileInfoList){
        if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        if(fileInfo.isDir()){    /* 当为目录时，递归的进行copy */
            if(!copyDir(fileInfo.filePath(),
                targetDir.filePath(fileInfo.fileName()),
                coverFileIfExist))
                return false;
        }
        else{            /* 当允许覆盖操作时，将旧文件进行删除操作 */
            if(coverFileIfExist && targetDir.exists(fileInfo.fileName())){
                targetDir.remove(fileInfo.fileName());
            }

            // 进行文件copy
            if(!QFile::copy(fileInfo.filePath(),
                targetDir.filePath(fileInfo.fileName()))){
                    return false;
            }
        }
    }
    return true;
}

//清除文本框内容
void Widget::clearText()
{
    ui->lineEdit->clear();
    ui->lineEdit_2->clear();
    ui->textEdit->clear();
    ui->textEdit_2->clear();
    qDebug() << "清除文本框";
}

//拷贝文件
void Widget::copyfile(QString src, QString dst)
{
    //QString sourceFile = "/home/llp/test/source.txt";
    //QString toFile = "/home/llp/test/to.txt";
    //QFile::copy(sourceFile, toFile); 只能拷贝不存在的文本，不能做到只复制内容
    QFile file(src);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "fileopen error";
        return ;
    }
    QFile data(dst);
    if (!data.open(QIODevice::WriteOnly | QIODevice::Truncate )) {
        qDebug() << "fileopen error";
        return;
    }
    QTextStream out(&data);
    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine();
        out << line << "\n";
        //qDebug() << line ;
    }

    qDebug() << "拷贝文件" << src << "-->" << dst;
}

//创建文件
void Widget::createFile(QString filePath, QString fileName)
{
    QDir tempDir(filePath);
    //临时保存程序当前路径
    QString currentDir = tempDir.currentPath();
    QFile *tempFile = new QFile;
    //将程序的执行路径设置到filePath下
    tempDir.setCurrent(filePath);
    //此时，路径下没有fileName文件，使用下面代码在当前路径下创建文件
    tempFile->setFileName(fileName);
    //将程序当前路径设置为原来的路径
    tempDir.setCurrent(currentDir);
    qDebug() << "在" << filePath << "下" << "创建" << fileName;
}

//同步slot A-->B B-->A A=B
void Widget::AtoB()
{
    QProgressDialog dialog(tr("任务进度"), tr("取消"), 0, sum, this);
    dialog.setWindowTitle(tr("进度对话框"));
    dialog.setWindowModality(Qt::WindowModal);
    dialog.show();
    for(int i = 0; i < sum; i++)
    {
        dialog.setValue(i);
        QCoreApplication::processEvents();
        if(dialog.wasCanceled())
            break;
         QThread::msleep(10);
    }
    QString src = ui->lineEdit_2->text();
    QString dst = ui->lineEdit->text();
    to_AB(src, dst);
    dialog.setValue(sum);
    qDebug() << "将" << src << "同步到" << dst;
    QMessageBox::information(NULL, "文件备份", "文件A已同步到文件B", QMessageBox::Yes);
}

void Widget::BtoA()
{
    QProgressDialog dialog(tr("任务进度"), tr("取消"), 0, sum, this);
    dialog.setWindowTitle(tr("进度对话框"));
    dialog.setWindowModality(Qt::WindowModal);
    dialog.show();
    for(int i = 0; i < sum; i++)
    {
        dialog.setValue(i);
        QCoreApplication::processEvents();
        if(dialog.wasCanceled())
            break;
         QThread::msleep(10);
    }
    QString dst = ui->lineEdit_2->text();
    QString src = ui->lineEdit->text();
    to_AB(src, dst);
    dialog.setValue(sum);
    qDebug() << "将" << src << "同步到" << dst;
    QMessageBox::information(NULL, "文件备份", "文件B已同步到文件A", QMessageBox::Yes);
}

void Widget::ComAB()
{
    QProgressDialog dialog(tr("任务进度"), tr("取消"), 0, sum, this);
    dialog.setWindowTitle(tr("进度对话框"));
    dialog.setWindowModality(Qt::WindowModal);
    dialog.show();
    for(int i = 0; i < sum; i++)
    {
        dialog.setValue(i);
        QCoreApplication::processEvents();
        if(dialog.wasCanceled())
            break;
         QThread::msleep(10);
    }
    QString path1 = ui->lineEdit_2->text();
    QString path2 = ui->lineEdit->text();
    comAB(path1, path2);
    dialog.setValue(sum);
    qDebug() << "同步"<< path1 << " " << path2;
    QMessageBox::information(NULL, "文件备份", "文件AB已同时同步", QMessageBox::Yes);
}

//function realise
void Widget::to_AB(QString src, QString dst)
{
    //src open and sort
    QDir srcDir(src);
    srcDir.setFilter(QDir::Files|QDir::Dirs);
    srcDir.setSorting(QDir::Name);
    QFileInfoList srcList = srcDir.entryInfoList();
    //dst open and sort
    QDir dstDir(dst);
    dstDir.setFilter(QDir::Files|QDir::Dirs);
    dstDir.setSorting(QDir::Name);
    QFileInfoList dstList = dstDir.entryInfoList();
    //遍历两目录
    int p1 = 0;
    int p2 = 0;
    QFileInfo srcFile;
    QFileInfo dstFile;
    while(p1 < srcList.size() && p2 < dstList.size()) {
        srcFile = srcList.at(p1);
        dstFile = dstList.at(p2);
        if (srcFile.fileName() == "." || srcFile.fileName() == ".."){
            p1++;
            continue;
        }
        if (dstFile.fileName() == "." || dstFile.fileName() == ".."){
            p2++;
            continue;
        }
        if (QString::compare(srcFile.fileName(), dstFile.fileName()) > 0) {
            if (dstFile.isDir()) {
                QString delPath = dstFile.absoluteFilePath();
                QDir dir;
                dir.setPath(delPath);
                dir.removeRecursively();
            } else {
                dstDir.remove(dstFile.fileName());
            }
            p2++;
        } else if (QString::compare(srcFile.fileName(), dstFile.fileName()) < 0) {
            QString dstPath = dst;
            dstPath.append("/");
            dstPath.append(srcFile.fileName());
            if (srcFile.isDir()) {
                dstDir.mkdir(dstPath);
                copyDir(srcFile.absoluteFilePath(), dstPath, false);
            } else {
                createFile(dst, srcFile.fileName());
                copyfile(srcFile.absoluteFilePath(), dstPath);
            }
            p1++;
        } else if (srcFile.isDir() && dstFile.isDir()){
            to_AB(srcFile.absoluteFilePath(), dstFile.absoluteFilePath());
            p1++; p2++;
        } else {
           //获取srcFile的Md5值
           QFile sfile(srcFile.absoluteFilePath());
           sfile.open(QIODevice::ReadOnly);
           QByteArray s = QCryptographicHash::hash(sfile.readAll(), QCryptographicHash::Md5);
           sfile.close();
           QString s_Md5 = s.toHex();
           //获取dstFile的Md5值
           QFile dfile(dstFile.absoluteFilePath());
           dfile.open(QIODevice::ReadOnly);
           QByteArray d = QCryptographicHash::hash(dfile.readAll(), QCryptographicHash::Md5);
           dfile.close();
           QString d_Md5 = d.toHex();
           //compare Md5
           if (QString::compare(s_Md5, d_Md5) != 0){
               copyfile(srcFile.absoluteFilePath(), dstFile.absoluteFilePath());
           }
           p1++; p2++;
        }

    }

    //copy
    while (p1 < srcList.size()) {
        srcFile = srcList.at(p1);
        if (srcFile.fileName() == "." || srcFile.fileName() == "..") {
            p1++;
            continue;
        }
        QString dstPath = dst;
        dstPath.append("/");
        dstPath.append(srcFile.fileName());
        if (srcFile.isDir()) {
            dstDir.mkdir(dstPath);
            copyDir(srcFile.absoluteFilePath(), dstPath, false);
        } else {
            createFile(dst, srcFile.fileName());
            copyfile(srcFile.absoluteFilePath(), dstPath);
        }
        p1++;
    }
    //delete
    while(p2 < dstList.size()) {
        dstFile = dstList.at(p2);
        if (dstFile.fileName() == "." || dstFile.fileName() == "..") {
            p2++;
            continue;
        }
        if (dstFile.isDir()) {
            QString delPath = dstFile.absoluteFilePath();
            QDir dir;
            dir.setPath(delPath);
            dir.removeRecursively();
        } else {
            dstDir.remove(dstFile.fileName());
        }
        p2++;
    }
    
}

void Widget::comAB(QString src, QString dst)
{
    //src open and sort
    QDir srcDir(src);
    srcDir.setFilter(QDir::Files|QDir::Dirs);
    srcDir.setSorting(QDir::Name);
    QFileInfoList srcList = srcDir.entryInfoList();
    //dst open and sort
    QDir dstDir(dst);
    dstDir.setFilter(QDir::Files|QDir::Dirs);
    dstDir.setSorting(QDir::Name);
    QFileInfoList dstList = dstDir.entryInfoList();
    //遍历两目录
    int p1 = 0;
    int p2 = 0;
    QFileInfo srcFile;
    QFileInfo dstFile;
    while(p1 < srcList.size() && p2 < dstList.size()) {
        srcFile = srcList.at(p1);
        dstFile = dstList.at(p2);
        if (srcFile.fileName() == "." || srcFile.fileName() == ".."){
            p1++;
            continue;
        }
        if (dstFile.fileName() == "." || dstFile.fileName() == ".."){
            p2++;
            continue;
        }
        if (QString::compare(srcFile.fileName(), dstFile.fileName()) > 0) {
            QString dstPath = src;
            dstPath.append("/");
            dstPath.append(dstFile.fileName());
            if (dstFile.isDir()) {
                srcDir.mkdir(dstPath);
                copyDir(dstFile.absoluteFilePath(), dstPath, false);
            } else {
                createFile(src, dstFile.fileName());
                copyfile(dstFile.absoluteFilePath(), dstPath);
            }
            p2++;
        } else if (QString::compare(srcFile.fileName(), dstFile.fileName()) < 0) {
            QString dstPath = dst;
            dstPath.append("/");
            dstPath.append(srcFile.fileName());
            if (srcFile.isDir()) {
                dstDir.mkdir(dstPath);
                copyDir(srcFile.absoluteFilePath(), dstPath, false);
            } else {
                createFile(dst, srcFile.fileName());
                copyfile(srcFile.absoluteFilePath(), dstPath);
            }
            p1++;
        } else if (srcFile.isDir() && dstFile.isDir()){
            comAB(srcFile.absoluteFilePath(), dstFile.absoluteFilePath());
            p1++; p2++;
        } else {
           //获取srcFile的Md5值
           QFile sfile(srcFile.absoluteFilePath());
           sfile.open(QIODevice::ReadOnly);
           QByteArray s = QCryptographicHash::hash(sfile.readAll(), QCryptographicHash::Md5);
           sfile.close();
           QString s_Md5 = s.toHex();
           //获取dstFile的Md5值
           QFile dfile(dstFile.absoluteFilePath());
           dfile.open(QIODevice::ReadOnly);
           QByteArray d = QCryptographicHash::hash(dfile.readAll(), QCryptographicHash::Md5);
           dfile.close();
           QString d_Md5 = d.toHex();
           //compare Md5
           if (QString::compare(s_Md5, d_Md5) != 0){
               QString stime = srcFile.lastModified().toString("yyyy-MM-dd hh:mm:ss");
               QString dtime = dstFile.lastModified().toString("yyyy-MM-dd hh:mm:ss");
               if (QString::compare(stime, dtime) > 0) {
                   copyfile(srcFile.absoluteFilePath(), dstFile.absoluteFilePath());
               } else {
                   copyfile(dstFile.absoluteFilePath(), srcFile.absoluteFilePath());
               }
           }
           p1++; p2++;
        }

    }

    //copy
    while (p1 < srcList.size()) {
        srcFile = srcList.at(p1);
        if (srcFile.fileName() == "." || srcFile.fileName() == "..") {
            p1++;
            continue;
        }
        QString dstPath = dst;
        dstPath.append("/");
        dstPath.append(srcFile.fileName());
        if (srcFile.isDir()) {
            dstDir.mkdir(dstPath);
            copyDir(srcFile.absoluteFilePath(), dstPath, false);
        } else {
            createFile(dst, srcFile.fileName());
            copyfile(srcFile.absoluteFilePath(), dstPath);
        }
        p1++;
    }
    //copy
    while(p2 < dstList.size()) {
        dstFile = dstList.at(p2);
        if (dstFile.fileName() == "." || dstFile.fileName() == "..") {
            p2++;
            continue;
        }
        QString dstPath = src;
        dstPath.append("/");
        dstPath.append(dstFile.fileName());
        if (dstFile.isDir()) {
            srcDir.mkdir(dstPath);
            copyDir(dstFile.absoluteFilePath(), dstPath, false);
        } else {
            createFile(dst, dstFile.fileName());
            copyfile(dstFile.absoluteFilePath(), dstPath);
        }
        p2++;
    }
}

Widget::~Widget()
{
    delete ui;
}

